International aid may take the form of multilateral aid – provided
through international bodies such as the UN, or NGOs such as Oxfam – or
bilateral aid, which operates on a government-to-government basis. There
is considerable debate about whether international aid works, in the
sense of reducing poverty and stimulating development.
However, the effectiveness of aid is often diluted by corruption. Aid
is invariably channeled through the governments of recipient countries,
in which power is often concentrated in the hands of a few politicians
and bureaucrats, and the mechanisms of accountability are, at best,
poorly developed. This tends to benefit corrupt leaders and elites
rather than the people, projects and programs for which it was
intended.
The hypothesis that foreign aid can promote growth in developing
countries was explored, using panel data series for foreign aid, while
accounting for regional differences in Asian, African, Latin American,
and the Caribbean countries as well as the differences in income levels,
the results of this study also indicate that foreign aid has mixed
effects on economic growth in developing countries.
This study examines the relationships between foreign aid,
institutional structure, and economic performance for 80 countries in
Europe, America, Africa, and Asia. It is found that official development
assistance and the quality of institutional structure in the sample
countries affect economic growth positively.
Cargando Librerias
Algunas librerias y paquetes usados para obtener y descargar los
datos
library(tidyverse) # i don't think I´ll use this /r
── Attaching core tidyverse packages ───────────────────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.4 ✔ readr 2.1.5
✔ forcats 1.0.0 ✔ stringr 1.5.1
✔ ggplot2 3.5.1 ✔ tibble 3.2.1
✔ lubridate 1.9.3 ✔ tidyr 1.3.1
✔ purrr 1.0.2 ── Conflicts ─────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(WDI) # for World Bank data acceding (mostly country code names)
library(readxl) # for excel files reading
library(readr) # for csv files reading
library(visdat) # for data visualization
library(plotly) # for plots
Adjuntando el paquete: ‘plotly’
The following object is masked from ‘package:ggplot2’:
last_plot
The following object is masked from ‘package:stats’:
filter
The following object is masked from ‘package:graphics’:
layout
library(purrr) # for map funciton
Obtener datos
Datos para paises bajos ingresos sean utilizados, segun clasificación
del banco mundial, hay 26 paises de bajos ingresos y 51 de ingresos
medios bajos
country_class <- read_excel("CLASS.xlsx")
country_class %>%
filter(!is.na(Region), !is.na(`Income group`)) %>%
group_by(`Income group`) %>%
summarise(countries = n())
Listado de paises a analisar:
my_countries <- country_class %>%
filter(!is.na(Region), `Income group` %in% c('Low income', 'Lower middle income')) %>%
select(Code)
my_countries
Hacer la respectiva asociacion de nombres iso3c e iso2c
my_countries$iso2c <- WDI_data$country %>%
filter(iso3c %in% my_countries$Code) %>%
.$iso2c
my_countries
Datos del banco mundial (para ODA y los indices de gobernanza) y el
Human Development Reports API son descargados desde scripts de Python.
Son almacenados en archivos CSV y luego son cargados aqui:
HDI
datos_HDI <- read_csv("datos_python_HDI.csv", col_names = c('Code', 'iso2c', 'indicator', 'year', 'value'),
col_types = list(col_character(), col_character(), col_character(), col_double(), col_double()))
hdi_indicators <- datos_HDI %>% distinct(indicator) %>% .$indicator
ODA
oda_indicators <- c(
'DT_ODA_ALLD_CD',
'DT_ODA_ALLD_KD',
'DT_ODA_OATL_CD',
'DT_ODA_OATL_KD',
'DT_ODA_ODAT_CD',
'DT_ODA_ODAT_GI_ZS',
'DT_ODA_ODAT_GN_ZS',
'DT_ODA_ODAT_KD',
'DT_ODA_ODAT_MP_ZS',
'DT_ODA_ODAT_PC_ZS',
'DT_ODA_ODAT_XP_ZS'
)
gob_indicators <- c(
'CC_EST',
'CC_NO_SRC',
'CC_PER_RNK',
'CC_PER_RNK_LOWER',
'CC_PER_RNK_UPPER',
'CC_STD_ERR',
'GE_EST',
'GE_NO_SRC',
'GE_PER_RNK',
'GE_PER_RNK_LOWER',
'GE_PER_RNK_UPPER',
'GE_STD_ERR',
'PV_EST',
'PV_NO_SRC',
'PV_PER_RNK',
'PV_PER_RNK_LOWER',
'PV_PER_RNK_UPPER',
'PV_STD_ERR',
'RQ_EST',
'RQ_NO_SRC',
'RQ_PER_RNK',
'RQ_PER_RNK_LOWER',
'RQ_PER_RNK_UPPER',
'RQ_STD_ERR',
'RL_EST')
datos_WB <- data.frame(indicator = character(), iso2c = character(), year = double(), value = double())
suppressWarnings(
for (indicator in c(oda_indicators, gob_indicators)) {
datos_WB <- rbind(datos_WB, read_csv(paste("datos_python", indicator, ".csv", sep =''),
col_names = c('indicator', 'iso2c', 'year', 'value'),
col_types = list(col_character(), col_character(), col_double(), col_double())))
}
)
Manipulacion de Datos
Transformar la estructura de los datos para una mejor comprension
datos_paper <- rbind(datos_WB, datos_HDI %>% select(indicator, iso2c, year, value)) %>%
pivot_wider(names_from = indicator, values_from = value)
Revisar que datos estan como faltantes




Tomando en cuenta los datos faltantes, hacer filtros para seleccionar
una muestra mas pequeña
datos_paper %>% filter(is.na(DT.ODA.ALLD.CD)) ## SS (South Sudan) y ZW (Zimbabwe) faltantes de ODA y GOB indicators
datos_paper %>% filter(!iso2c %in% c('SS', 'ZW')) %>% filter(is.na(CC.EST)) %>% group_by(year) %>% summarise(times = n())
# para años 1995, 1997, 1999 y 2001 no hay registros de GOB
# 1996, 1998, 2000, 2002 and 2003 tiene algunos paises sin datos
datos_paper %>% arrange(year) %>% filter(!iso2c %in% c('SS', 'ZW'), !year %in% c(1995, 1997, 1999, 2001)) %>%
filter(is.na(CC.EST)) # FM (Micronesia), KI (Kiribati) y TL (Timor-Leste) no tiene GOB in en estos años
# tambien CV (Cabo Verde) and SB (Solomon Islands) no registro GOB en 2000 - 2003
Ver datos aplicando los filtros determinados en las busquedas pasadas
antes del 2001 suele tener informacion faltante BT (Bhutan), ER
(Eritrea), GW (Guinea-Bissau), KP (North Korea), LB (Lebanon), NG
(Nigeria), PS (Palestine), SO (Somalia), VU (Vanuatu) son paises sin
registro de hdi

De 1925 observaciones reducimos a 1098
Probando un modelo sencillo Minimos cuadrados
model <- lm(hdi ~ DT.ODA.ALLD.CD + CC.EST + GE.EST + PV.EST + RQ.EST + RL.EST, data=datos_model)
summary(model)
Call:
lm(formula = hdi ~ DT.ODA.ALLD.CD + CC.EST + GE.EST + PV.EST +
RQ.EST + RL.EST, data = datos_model)
Residuals:
Min 1Q Median 3Q Max
-0.291363 -0.060809 0.001437 0.062167 0.195139
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 5.881e-01 5.818e-03 101.081 < 2e-16 ***
DT.ODA.ALLD.CD 2.008e-12 2.589e-12 0.776 0.43815
CC.EST -6.896e-02 1.085e-02 -6.355 3.05e-10 ***
GE.EST 1.533e-01 1.107e-02 13.849 < 2e-16 ***
PV.EST 9.200e-03 4.513e-03 2.039 0.04172 *
RQ.EST -3.501e-02 1.065e-02 -3.288 0.00104 **
RL.EST 2.094e-02 1.204e-02 1.738 0.08243 .
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.08902 on 1091 degrees of freedom
Multiple R-squared: 0.2893, Adjusted R-squared: 0.2854
F-statistic: 74 on 6 and 1091 DF, p-value: < 2.2e-16
Todas las variables son significativas al 95% excepto ODA
Se revisara las relaciones entre las variables graficamente
#Visualizacion de datos
my_plot <- list()
for (col in colnames(datos_model)[4:33]) {
my_plot[[col]] <- plot_ly(x = datos_model[[col]], y = datos_model[[3]],
type = 'scatter', mode = 'markers', name = paste(col, "vs HDI"))
}
subplot(my_plot[1:5], nrows = 2, margin = 0.05) %>% layout(title = 'ODA vs HDI')
NA
subplot(my_plot[6:11], nrows = 2, margin = 0.05) %>% layout(title = 'CC vs HDI')
subplot(my_plot[12:17], nrows = 2, margin = 0.05) %>% layout(title = 'GE vs HDI')
subplot(my_plot[18:23], nrows = 2, margin = 0.05) %>% layout(title = 'PV vs HDI')
subplot(my_plot[24:29], nrows = 2, margin = 0.05) %>% layout(title = 'RQ vs HDI')
subplot(my_plot[30], nrows = 1, margin = 0.05) %>% layout(title = 'RL vs HDI')
No se ve una relacion clara, hay tanto paises con punteos altos y
bajos de GOB que tienen tanto HID altos o bajos Quiza puede verse una
leve relacion de mayor punteo en GOB acompañado de mejor punteo den
HDI
Se realizara el mismo proceso con el crecimiento o decrecimiento de
HDI anual (no se perderan datos al calcular la diferencia porque se
añade el año 2001 en la seleccion)
Manipulacion de datos utilizando operador diferencia


Construccion de graficos
subplot(my_plot_3[6:11], nrows = 2, margin = 0.05) %>% layout(title = 'CC vs HDI diff')
subplot(my_plot_3[12:17], nrows = 2, margin = 0.05) %>% layout(title = 'GE vs HDI diff')
subplot(my_plot_3[18:23], nrows = 2, margin = 0.05) %>% layout(title = 'PV vs HDI diff')
subplot(my_plot_3[24:29], nrows = 2, margin = 0.05) %>% layout(title = 'RQ vs HDI diff')
subplot(my_plot_3[30], nrows = 1, margin = 0.05) %>% layout(title = 'RL vs HDI diff')
Probar un nuevo modelo usadno ahora como variable dependiente
hdi_diff
model_3 <- lm(hdi_diff ~ DT.ODA.ALLD.CD + CC.EST + GE.EST + PV.EST + RQ.EST + RL.EST, data=datos_model_3)
summary(model_3)
Call:
lm(formula = hdi_diff ~ DT.ODA.ALLD.CD + CC.EST + GE.EST + PV.EST +
RQ.EST + RL.EST, data = datos_model_3)
Residuals:
Min 1Q Median 3Q Max
-0.084650 -0.002575 0.000074 0.002727 0.074605
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 6.437e-03 4.444e-04 14.485 < 2e-16 ***
DT.ODA.ALLD.CD -6.826e-14 1.978e-13 -0.345 0.73005
CC.EST 6.344e-04 8.289e-04 0.765 0.44421
GE.EST 2.211e-03 8.457e-04 2.615 0.00905 **
PV.EST 1.058e-03 3.448e-04 3.070 0.00219 **
RQ.EST -1.227e-03 8.134e-04 -1.509 0.13169
RL.EST -2.355e-03 9.200e-04 -2.560 0.01060 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.006801 on 1091 degrees of freedom
Multiple R-squared: 0.01844, Adjusted R-squared: 0.01304
F-statistic: 3.416 on 6 and 1091 DF, p-value: 0.002404
Otro modelo ahora usando las variables PER.RNK en vex de EST
model_4 <- lm(hdi_diff ~ DT.ODA.ALLD.CD + CC.PER.RNK + GE.PER.RNK + PV.PER.RNK + RQ.PER.RNK + RL.EST, data=datos_model_3)
summary(model_4)
Call:
lm(formula = hdi_diff ~ DT.ODA.ALLD.CD + CC.PER.RNK + GE.PER.RNK +
PV.PER.RNK + RQ.PER.RNK + RL.EST, data = datos_model_3)
Residuals:
Min 1Q Median 3Q Max
-0.085300 -0.002458 0.000048 0.002847 0.074421
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 4.239e-03 1.620e-03 2.616 0.00902 **
DT.ODA.ALLD.CD -2.927e-13 1.917e-13 -1.527 0.12711
CC.PER.RNK 2.002e-05 2.154e-05 0.930 0.35272
GE.PER.RNK 4.254e-05 2.599e-05 1.637 0.10192
PV.PER.RNK 9.925e-06 1.451e-05 0.684 0.49422
RQ.PER.RNK -3.012e-05 2.547e-05 -1.182 0.23733
RL.EST -1.296e-03 9.288e-04 -1.395 0.16323
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.006842 on 1091 degrees of freedom
Multiple R-squared: 0.006585, Adjusted R-squared: 0.001122
F-statistic: 1.205 on 6 and 1091 DF, p-value: 0.3009
Viendo la historia de las variables en el tiempo (por pais)
LS0tDQp0aXRsZTogIk9mZmljaWFsIERldmVsb3BtZW50IEFzc2lzdGFuY2UgYW5kIEluc3RpdHV0aW9uYWwgUXVhbGl0eSBvbiBVbmRldmVsb3BlZCBjb3VudHJpZXMiDQphdXRob3I6ICJPc2NhciBFZHVhcmRvIE1vcmFsZXMgQ8OhcmRlbmFzIg0KZGF0ZTogIjIwMjQtMDgtMDUiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KDQpJbnRlcm5hdGlvbmFsIGFpZCBtYXkgdGFrZSB0aGUgZm9ybSBvZiBtdWx0aWxhdGVyYWwgYWlkIOKAkyBwcm92aWRlZCB0aHJvdWdoIGludGVybmF0aW9uYWwgYm9kaWVzIHN1Y2ggYXMgdGhlIFVOLCBvciBOR09zIHN1Y2ggYXMgT3hmYW0g4oCTIG9yIGJpbGF0ZXJhbCBhaWQsIHdoaWNoIG9wZXJhdGVzIG9uIGEgZ292ZXJubWVudC10by1nb3Zlcm5tZW50IGJhc2lzLiBUaGVyZSBpcyBjb25zaWRlcmFibGUgZGViYXRlIGFib3V0IHdoZXRoZXIgaW50ZXJuYXRpb25hbCBhaWQgd29ya3MsIGluIHRoZSBzZW5zZSBvZiByZWR1Y2luZyBwb3ZlcnR5IGFuZCBzdGltdWxhdGluZyBkZXZlbG9wbWVudC4NCg0KSG93ZXZlciwgdGhlIGVmZmVjdGl2ZW5lc3Mgb2YgYWlkIGlzIG9mdGVuIGRpbHV0ZWQgYnkgY29ycnVwdGlvbi4gQWlkIGlzIGludmFyaWFibHkgY2hhbm5lbGVkIHRocm91Z2ggdGhlIGdvdmVybm1lbnRzIG9mIHJlY2lwaWVudCBjb3VudHJpZXMsIGluIHdoaWNoIHBvd2VyIGlzIG9mdGVuIGNvbmNlbnRyYXRlZCBpbiB0aGUgaGFuZHMgb2YgYSBmZXcgcG9saXRpY2lhbnMgYW5kIGJ1cmVhdWNyYXRzLCBhbmQgdGhlIG1lY2hhbmlzbXMgb2YgYWNjb3VudGFiaWxpdHkgYXJlLCBhdCBiZXN0LCBwb29ybHkgZGV2ZWxvcGVkLiBUaGlzIHRlbmRzIHRvIGJlbmVmaXQgY29ycnVwdCBsZWFkZXJzIGFuZCBlbGl0ZXMgcmF0aGVyIHRoYW4gdGhlIHBlb3BsZSwgcHJvamVjdHMgYW5kIHByb2dyYW1zIGZvciB3aGljaCBpdCB3YXMgaW50ZW5kZWQuDQoNClx0ZXh0YmZ7V2F0dHMsIENhcmwuICgyMDE0KS4gUmU6IERvZXMgZm9yZWlnbiBhaWQgaGVscCB0aGUgZGV2ZWxvcGluZyBjb3VudHJpZXMgdG93YXJkcyBkZXZlbG9wbWVudD8uIFJldHJpZXZlZCBmcm9tOiAkaHR0cHM6Ly93d3cucmVzZWFyY2hnYXRlLm5ldC9wb3N0L0RvZXNfZm9yZWlnbl9haWRfaGVscF90aGVfZGV2ZWxvcGluZ19jb3VudHJpZXNfdG93YXJkc19kZXZlbG9wbWVudC81MzIyMDA1ZWQwMzliMWU3NjQ4YjQ1OWMvY2l0YXRpb24vZG93bmxvYWQuJH0NCg0KDQpUaGUgaHlwb3RoZXNpcyB0aGF0IGZvcmVpZ24gYWlkIGNhbiBwcm9tb3RlIGdyb3d0aCBpbiBkZXZlbG9waW5nIGNvdW50cmllcyB3YXMgZXhwbG9yZWQsIHVzaW5nIHBhbmVsIGRhdGEgc2VyaWVzIGZvciBmb3JlaWduIGFpZCwgd2hpbGUgYWNjb3VudGluZyBmb3IgcmVnaW9uYWwgZGlmZmVyZW5jZXMgaW4gQXNpYW4sIEFmcmljYW4sIExhdGluIEFtZXJpY2FuLCBhbmQgdGhlIENhcmliYmVhbiBjb3VudHJpZXMgYXMgd2VsbCBhcyB0aGUgZGlmZmVyZW5jZXMgaW4gaW5jb21lIGxldmVscywgdGhlIHJlc3VsdHMgb2YgdGhpcyBzdHVkeSBhbHNvIGluZGljYXRlIHRoYXQgZm9yZWlnbiBhaWQgaGFzIG1peGVkIGVmZmVjdHMgb24gZWNvbm9taWMgZ3Jvd3RoIGluIGRldmVsb3BpbmcgY291bnRyaWVzLg0KDQpcdGV4dGJme0VrYW5heWFrZSwgRS4gJiBDaGF0cm5hLCBEYXNoYS4gKDIwMTApLiBUaGUgZWZmZWN0IG9mIGZvcmVpZ24gYWlkIG9uIGVjb25vbWljIGdyb3d0aCBpbiBkZXZlbG9waW5nIGNvdW50cmllcy4gSm91cm5hbCBvZiBJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIGFuZCBDdWx0dXJhbCBTdHVkaWVzLiAzLn0NCg0KDQpUaGlzIHN0dWR5IGV4YW1pbmVzIHRoZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gZm9yZWlnbiBhaWQsIGluc3RpdHV0aW9uYWwgc3RydWN0dXJlLCBhbmQgZWNvbm9taWMgcGVyZm9ybWFuY2UgZm9yIDgwIGNvdW50cmllcyBpbiBFdXJvcGUsIEFtZXJpY2EsIEFmcmljYSwgYW5kIEFzaWEuIEl0IGlzIGZvdW5kIHRoYXQgb2ZmaWNpYWwgZGV2ZWxvcG1lbnQgYXNzaXN0YW5jZSBhbmQgdGhlIHF1YWxpdHkgb2YgaW5zdGl0dXRpb25hbCBzdHJ1Y3R1cmUgaW4gdGhlIHNhbXBsZSBjb3VudHJpZXMgYWZmZWN0IGVjb25vbWljIGdyb3d0aCBwb3NpdGl2ZWx5Lg0KDQpcdGV4dGJme0hheWFsb8SfbHUsIFDEsW5hci4gKDIwMjMpLiBGb3JlaWduIEFpZCwgSW5zdGl0dXRpb25zLCBhbmQgRWNvbm9taWMgUGVyZm9ybWFuY2UgaW4gRGV2ZWxvcGluZyBDb3VudHJpZXMuIEVza2nFn2VoaXIgT3NtYW5nYXppIMOcbml2ZXJzaXRlc2kgxLBrdGlzYWRpIHZlIMSwZGFyaSBCaWxpbWxlciBEZXJnaXNpLiAxOC4gNzQ4LTc2NS4gMTAuMTcxNTMvb2d1aWliZi4xMjc3MzQ4Ln0NCg0KIyBDYXJnYW5kbyBMaWJyZXJpYXMNCg0KQWxndW5hcyBsaWJyZXJpYXMgeSBwYXF1ZXRlcyB1c2Fkb3MgcGFyYSBvYnRlbmVyIHkgZGVzY2FyZ2FyIGxvcyBkYXRvcw0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKSAjIG1hbmVqbyBkZSBkYXRhZnJhbWVzDQpsaWJyYXJ5KFdESSkgICAgICAgIyBsaWJyZXJpYSBwYXJhIGFjY2VkZXIgYSBtZXRhZGF0YSBkZSBiYW5jbyBtdW5kaWFsDQpsaWJyYXJ5KHJlYWR4bCkgICAgIyBsZWVyIGFyY2hpdm9zIGRlIGV4Y2VsDQpsaWJyYXJ5KHJlYWRyKSAgICAgIyBsZWVyIGFyY2hpdm9zIGNzdg0KbGlicmFyeSh2aXNkYXQpICAgICMgdmlzdWFsaXphY2lvbiBkZSBkYXRvcyBjb21vIGdyYWZpY29zDQpsaWJyYXJ5KHBsb3RseSkgICAgIyBncmFmaWNvcw0KbGlicmFyeShwdXJycikgICAgICMgZnVuY2lvbiBtYXANCmBgYA0KDQojIE9idGVuZXIgZGF0b3MNCg0KRGF0b3MgcGFyYSBwYWlzZXMgYmFqb3MgaW5ncmVzb3Mgc2VhbiB1dGlsaXphZG9zLCBzZWd1biBjbGFzaWZpY2FjacOzbiBkZWwgYmFuY28gbXVuZGlhbCwgaGF5IDI2IHBhaXNlcyBkZSBiYWpvcyBpbmdyZXNvcyB5IDUxIGRlIGluZ3Jlc29zIG1lZGlvcyBiYWpvcw0KDQpgYGB7cn0NCmNvdW50cnlfY2xhc3MgPC0gcmVhZF9leGNlbCgiQ0xBU1MueGxzeCIpDQoNCmNvdW50cnlfY2xhc3MgJT4lDQogIGZpbHRlcighaXMubmEoUmVnaW9uKSwgIWlzLm5hKGBJbmNvbWUgZ3JvdXBgKSkgJT4lDQogIGdyb3VwX2J5KGBJbmNvbWUgZ3JvdXBgKSAlPiUNCiAgc3VtbWFyaXNlKGNvdW50cmllcyA9IG4oKSkNCmBgYA0KDQpMaXN0YWRvIGRlIHBhaXNlcyBhIGFuYWxpc2FyOg0KDQpgYGB7cn0NCm15X2NvdW50cmllcyA8LSBjb3VudHJ5X2NsYXNzICU+JQ0KICBmaWx0ZXIoIWlzLm5hKFJlZ2lvbiksIGBJbmNvbWUgZ3JvdXBgICVpbiUgYygnTG93IGluY29tZScsICdMb3dlciBtaWRkbGUgaW5jb21lJykpICU+JQ0KICBzZWxlY3QoQ29kZSkNCm15X2NvdW50cmllcw0KYGBgDQoNCkhhY2VyIGxhIHJlc3BlY3RpdmEgYXNvY2lhY2lvbiBkZSBub21icmVzIGlzbzNjIGUgaXNvMmMNCg0KYGBge3J9DQpteV9jb3VudHJpZXMkaXNvMmMgPC0gV0RJX2RhdGEkY291bnRyeSAlPiUNCiAgZmlsdGVyKGlzbzNjICVpbiUgbXlfY291bnRyaWVzJENvZGUpICU+JQ0KICAuJGlzbzJjDQpteV9jb3VudHJpZXMNCmBgYA0KDQpEYXRvcyBkZWwgYmFuY28gbXVuZGlhbCAocGFyYSBPREEgeSBsb3MgaW5kaWNlcyBkZSBnb2Jlcm5hbnphKSB5IGVsIEh1bWFuIERldmVsb3BtZW50IFJlcG9ydHMgQVBJIHNvbiBkZXNjYXJnYWRvcyBkZXNkZSBzY3JpcHRzIGRlIFB5dGhvbi4NClNvbiBhbG1hY2VuYWRvcyBlbiBhcmNoaXZvcyBDU1YgeSBsdWVnbyBzb24gY2FyZ2Fkb3MgYXF1aToNCg0KIyMgSERJDQoNCmBgYHtyfQ0KZGF0b3NfSERJIDwtIHJlYWRfY3N2KCJkYXRvc19weXRob25fSERJLmNzdiIsIGNvbF9uYW1lcyA9IGMoJ0NvZGUnLCAnaXNvMmMnLCAnaW5kaWNhdG9yJywgJ3llYXInLCAndmFsdWUnKSwgDQogICAgICAgICAgICAgICAgICAgICAgY29sX3R5cGVzID0gbGlzdChjb2xfY2hhcmFjdGVyKCksIGNvbF9jaGFyYWN0ZXIoKSwgY29sX2NoYXJhY3RlcigpLCBjb2xfZG91YmxlKCksIGNvbF9kb3VibGUoKSkpDQoNCmhkaV9pbmRpY2F0b3JzIDwtIGRhdG9zX0hESSAlPiUgZGlzdGluY3QoaW5kaWNhdG9yKSAlPiUgLiRpbmRpY2F0b3INCmBgYA0KDQojIyBPREENCg0KYGBge3J9DQpvZGFfaW5kaWNhdG9ycyA8LSBjKA0KJ0RUX09EQV9BTExEX0NEJywNCidEVF9PREFfQUxMRF9LRCcsDQonRFRfT0RBX09BVExfQ0QnLA0KJ0RUX09EQV9PQVRMX0tEJywNCidEVF9PREFfT0RBVF9DRCcsDQonRFRfT0RBX09EQVRfR0lfWlMnLA0KJ0RUX09EQV9PREFUX0dOX1pTJywNCidEVF9PREFfT0RBVF9LRCcsDQonRFRfT0RBX09EQVRfTVBfWlMnLA0KJ0RUX09EQV9PREFUX1BDX1pTJywNCidEVF9PREFfT0RBVF9YUF9aUycNCikNCmdvYl9pbmRpY2F0b3JzIDwtIGMoDQonQ0NfRVNUJywNCidDQ19OT19TUkMnLA0KJ0NDX1BFUl9STksnLA0KJ0NDX1BFUl9STktfTE9XRVInLA0KJ0NDX1BFUl9STktfVVBQRVInLA0KJ0NDX1NURF9FUlInLA0KJ0dFX0VTVCcsDQonR0VfTk9fU1JDJywNCidHRV9QRVJfUk5LJywNCidHRV9QRVJfUk5LX0xPV0VSJywNCidHRV9QRVJfUk5LX1VQUEVSJywNCidHRV9TVERfRVJSJywNCidQVl9FU1QnLA0KJ1BWX05PX1NSQycsDQonUFZfUEVSX1JOSycsDQonUFZfUEVSX1JOS19MT1dFUicsDQonUFZfUEVSX1JOS19VUFBFUicsDQonUFZfU1REX0VSUicsDQonUlFfRVNUJywNCidSUV9OT19TUkMnLA0KJ1JRX1BFUl9STksnLA0KJ1JRX1BFUl9STktfTE9XRVInLA0KJ1JRX1BFUl9STktfVVBQRVInLA0KJ1JRX1NURF9FUlInLA0KJ1JMX0VTVCcpDQoNCmRhdG9zX1dCIDwtIGRhdGEuZnJhbWUoaW5kaWNhdG9yID0gY2hhcmFjdGVyKCksIGlzbzJjID0gY2hhcmFjdGVyKCksIHllYXIgPSBkb3VibGUoKSwgdmFsdWUgPSBkb3VibGUoKSkNCg0Kc3VwcHJlc3NXYXJuaW5ncygNCiAgZm9yIChpbmRpY2F0b3IgaW4gYyhvZGFfaW5kaWNhdG9ycywgZ29iX2luZGljYXRvcnMpKSB7DQogICAgZGF0b3NfV0IgPC0gcmJpbmQoZGF0b3NfV0IsIHJlYWRfY3N2KHBhc3RlKCJkYXRvc19weXRob24iLCBpbmRpY2F0b3IsICIuY3N2Iiwgc2VwID0nJyksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbF9uYW1lcyA9IGMoJ2luZGljYXRvcicsICdpc28yYycsICd5ZWFyJywgJ3ZhbHVlJyksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sX3R5cGVzID0gbGlzdChjb2xfY2hhcmFjdGVyKCksIGNvbF9jaGFyYWN0ZXIoKSwgY29sX2RvdWJsZSgpLCBjb2xfZG91YmxlKCkpKSkNCiAgfQ0KKQ0KYGBgDQoNCiMgTWFuaXB1bGFjaW9uIGRlIERhdG9zDQoNClRyYW5zZm9ybWFyIGxhIGVzdHJ1Y3R1cmEgZGUgbG9zIGRhdG9zIHBhcmEgdW5hIG1lam9yIGNvbXByZW5zaW9uDQoNCmBgYHtyfQ0KZGF0b3NfcGFwZXIgPC0gcmJpbmQoZGF0b3NfV0IsIGRhdG9zX0hESSAlPiUgc2VsZWN0KGluZGljYXRvciwgaXNvMmMsIHllYXIsIHZhbHVlKSkgJT4lDQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBpbmRpY2F0b3IsIHZhbHVlc19mcm9tID0gdmFsdWUpDQpgYGANCg0KUmV2aXNhciBxdWUgZGF0b3MgZXN0YW4gY29tbyBmYWx0YW50ZXMNCg0KYGBge3J9DQp2aXNfZGF0KGRhdG9zX3BhcGVyICU+JSBzZWxlY3QoYWxsX29mKGdzdWIoIl8iLCAiLiIsIG9kYV9pbmRpY2F0b3JzKSkpKSANCiAgIyBEVC5PREEuT0FUTC5DRCBhbmQgRFQuT0RBLk9BVEwuS0QgZmFsdGFuDQogICMgRFQuT0RBLk9EQVQuR0kuWlMsIERULk9EQS5PREFULkdOLlpTLCBEVC5PREEuT0RBVC5NUC5aUyBhbmQgRFQuT0RBLk9EQVQuWFAuWlMgdGllbmVuIGZhbHRhcw0KICAjIFVuIHBhciBkZSBvY3VycmVuY2lhcyBwYWlzLWHDsW8gcXVlIGZhbHRhbiBkYXRvcw0KYGBgDQoNCmBgYHtyfQ0KdmlzX2RhdChkYXRvc19wYXBlciAlPiUgYXJyYW5nZSh5ZWFyKSAlPiUNCiAgICAgICAgICBzZWxlY3QoYWxsX29mKGdzdWIoIl8iLCAiLiIsIGdvYl9pbmRpY2F0b3JzKSkpKSANCiAgIyBEYXRvcyBkZWwgMjAwMCBwYXJhIGF0cmFzIHRpZW5lbiBlc3BhY2lvcyBmYWx0YW50ZXMgDQpgYGANCg0KYGBge3J9DQp2aXNfZGF0KGRhdG9zX3BhcGVyICU+JQ0KICAgICAgICAgIHNlbGVjdChhbGxfb2YoaGRpX2luZGljYXRvcnMpKSkgDQogICMgYWJyLCBjbzJfcHJvZCwgbGUsIGxlX2YsIGxlX20sIG1tciBzb24gbGFzIHBvY2FzIGNhdGVnb3JpYXMgc2luIGRhdG9zIGZhbHRhbnRlcw0KYGBgDQoNCmBgYHtyfQ0KdmlzX2RhdChkYXRvc19wYXBlciAlPiUgYXJyYW5nZSh5ZWFyKSAlPiUgc2VsZWN0KGhkaSkpIA0KICAjIGhkaSBmYWx0YW50ZSBlbiBtdWx0aXBsZXMgb2NhY2lvbmVzDQpgYGANCg0KVG9tYW5kbyBlbiBjdWVudGEgbG9zIGRhdG9zIGZhbHRhbnRlcywgaGFjZXIgZmlsdHJvcyBwYXJhIHNlbGVjY2lvbmFyIHVuYSBtdWVzdHJhIG1hcyBwZXF1ZcOxYQ0KYGBge3J9DQpkYXRvc19wYXBlciAlPiUgZmlsdGVyKGlzLm5hKERULk9EQS5BTExELkNEKSkgIyMgU1MgKFNvdXRoIFN1ZGFuKSB5IFpXIChaaW1iYWJ3ZSkgZmFsdGFudGVzIGRlIE9EQSB5IEdPQiBpbmRpY2F0b3JzDQoNCmRhdG9zX3BhcGVyICU+JSBmaWx0ZXIoIWlzbzJjICVpbiUgYygnU1MnLCAnWlcnKSkgJT4lIGZpbHRlcihpcy5uYShDQy5FU1QpKSAlPiUgZ3JvdXBfYnkoeWVhcikgJT4lIHN1bW1hcmlzZSh0aW1lcyA9IG4oKSkNCiAgIyBwYXJhIGHDsW9zIDE5OTUsIDE5OTcsIDE5OTkgeSAyMDAxIG5vIGhheSByZWdpc3Ryb3MgZGUgR09CDQogICMgMTk5NiwgMTk5OCwgMjAwMCwgMjAwMiBhbmQgMjAwMyB0aWVuZSBhbGd1bm9zIHBhaXNlcyBzaW4gZGF0b3MNCmRhdG9zX3BhcGVyICU+JSBhcnJhbmdlKHllYXIpICU+JSBmaWx0ZXIoIWlzbzJjICVpbiUgYygnU1MnLCAnWlcnKSwgIXllYXIgJWluJSBjKDE5OTUsIDE5OTcsIDE5OTksIDIwMDEpKSAlPiUNCiAgICAgICAgICAgICAgICBmaWx0ZXIoaXMubmEoQ0MuRVNUKSkgIyBGTSAoTWljcm9uZXNpYSksIEtJIChLaXJpYmF0aSkgeSBUTCAoVGltb3ItTGVzdGUpIG5vIHRpZW5lIEdPQiBpbiBlbiBlc3RvcyBhw7FvcyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0YW1iaWVuIENWIChDYWJvIFZlcmRlKSBhbmQgU0IgKFNvbG9tb24gSXNsYW5kcykgbm8gcmVnaXN0cm8gR09CIGVuIDIwMDAgLSAyMDAzDQpgYGANClZlciBkYXRvcyBhcGxpY2FuZG8gbG9zIGZpbHRyb3MgZGV0ZXJtaW5hZG9zIGVuIGxhcyBidXNxdWVkYXMgcGFzYWRhcw0KYW50ZXMgZGVsIDIwMDEgc3VlbGUgdGVuZXIgaW5mb3JtYWNpb24gZmFsdGFudGUNCkJUIChCaHV0YW4pLCBFUiAoRXJpdHJlYSksIEdXIChHdWluZWEtQmlzc2F1KSwgS1AgKE5vcnRoIEtvcmVhKSwgTEIgKExlYmFub24pLCBORyAoTmlnZXJpYSksIFBTIChQYWxlc3RpbmUpLCBTTyAoU29tYWxpYSksIFZVIChWYW51YXR1KSBzb24gcGFpc2VzIHNpbiByZWdpc3RybyBkZSBoZGkNCmBgYHtyfQ0KZGF0b3NfcGFwZXIgJT4lIA0KICAgICAgICAgIGFycmFuZ2UoaXNvMmMpICU+JSANCiAgICAgICAgICBmaWx0ZXIoIWlzbzJjICVpbiUgYygnU1MnLCdaVycsJ0JUJywnRVInLCdHVycsJ0tQJywnTEInLCdORycsJ1BTJywnU08nLCdWVScsJ0ZNJywnS0knLCdUTCcsJ0NCJywnQ1YnLCdTQicpLCANCiAgICAgICAgICAgICAgICAgIXllYXIgJWluJSBjKDE5OTUsIDE5OTYsIDE5OTcsIDE5OTgsIDE5OTksIDIwMDAsIDIwMDEpKSAlPiUNCiAgICAgICAgICBzZWxlY3QoaXNvMmMsIHllYXIsIGhkaSwNCiAgICAgICAgICAgICAgICAgYWxsX29mKGdzdWIoIl8iLCAiLiIsIGdvYl9pbmRpY2F0b3JzKSkNCiAgICAgICAgICAgICAgICAgKQ0KDQpgYGANCg0KYGBge3J9DQp2aXNfZGF0KGRhdG9zX3BhcGVyICU+JSANCiAgICAgICAgZmlsdGVyKCFpc28yYyAlaW4lIGMoJ1NTJywgJ1pXJywgJ0JUJywgJ0VSJywgJ0dXJywgJ0tQJywgJ0xCJywgJ05HJywgJ1BTJywgJ1NPJywgJ1ZVJywgJ0ZNJywgJ0tJJywgJ1RMJywgJ0NWJywgJ1NCJyksDQogICAgICAgICAgICAgICAheWVhciAlaW4lIGMoMTk5NSwgMTk5NiwgMTk5NywgMTk5OCwgMTk5OSwgMjAwMCwgMjAwMSkpICU+JQ0KICAgICAgICBzZWxlY3QoaXNvMmMsIHllYXIsIGhkaSwgRFQuT0RBLkFMTEQuQ0QsIERULk9EQS5BTExELktELCBEVC5PREEuT0RBVC5DRCwgRFQuT0RBLk9EQVQuS0QsIERULk9EQS5PREFULlBDLlpTLA0KICAgICAgICAgICAgICAgYWxsX29mKGdzdWIoIl8iLCAiLiIsIGdvYl9pbmRpY2F0b3JzKSkNCiAgICAgICAgICAgICAgICkpDQpgYGANCkRlIDE5MjUgb2JzZXJ2YWNpb25lcyByZWR1Y2ltb3MgYSAxMDk4DQpgYGB7cn0NCmRhdG9zX21vZGVsIDwtIGRhdG9zX3BhcGVyICU+JSANCiAgICAgICAgZmlsdGVyKCFpc28yYyAlaW4lIGMoJ1NTJywgJ1pXJywgJ0JUJywgJ0VSJywgJ0dXJywgJ0tQJywgJ0xCJywgJ05HJywgJ1BTJywgJ1NPJywgJ1ZVJywgJ0ZNJywgJ0tJJywgJ1RMJywgJ0NWJywgJ1NCJyksDQogICAgICAgICAgICAgICAheWVhciAlaW4lIGMoMTk5NSwgMTk5NiwgMTk5NywgMTk5OCwgMTk5OSwgMjAwMCwgMjAwMSkpICU+JQ0KICAgICAgICBzZWxlY3QoaXNvMmMsIHllYXIsIGhkaSwgRFQuT0RBLkFMTEQuQ0QsIERULk9EQS5BTExELktELCBEVC5PREEuT0RBVC5DRCwgRFQuT0RBLk9EQVQuS0QsIERULk9EQS5PREFULlBDLlpTLA0KICAgICAgICAgICAgICAgYWxsX29mKGdzdWIoIl8iLCAiLiIsIGdvYl9pbmRpY2F0b3JzKSkNCiAgICAgICAgICAgICAgICkNCmBgYA0KDQpQcm9iYW5kbyB1biBtb2RlbG8gc2VuY2lsbG8gTWluaW1vcyBjdWFkcmFkb3MNCmBgYHtyfQ0KbW9kZWwgPC0gbG0oaGRpIH4gRFQuT0RBLkFMTEQuQ0QgKyBDQy5FU1QgKyBHRS5FU1QgKyBQVi5FU1QgKyBSUS5FU1QgKyBSTC5FU1QsIGRhdGE9ZGF0b3NfbW9kZWwpDQpzdW1tYXJ5KG1vZGVsKQ0KYGBgDQpUb2RhcyBsYXMgdmFyaWFibGVzIHNvbiBzaWduaWZpY2F0aXZhcyBhbCA5NSUgZXhjZXB0byBPREENCg0KU2UgcmV2aXNhcmEgbGFzIHJlbGFjaW9uZXMgZW50cmUgbGFzIHZhcmlhYmxlcyBncmFmaWNhbWVudGUNCg0KI1Zpc3VhbGl6YWNpb24gZGUgZGF0b3MNCg0KYGBge3J9DQpteV9wbG90ICA8LSBsaXN0KCkNCg0KZm9yIChjb2wgaW4gY29sbmFtZXMoZGF0b3NfbW9kZWwpWzQ6MzNdKSB7DQogIG15X3Bsb3RbW2NvbF1dIDwtIHBsb3RfbHkoeCA9IGRhdG9zX21vZGVsW1tjb2xdXSwgeSA9IGRhdG9zX21vZGVsW1szXV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdtYXJrZXJzJywgbmFtZSA9IHBhc3RlKGNvbCwgInZzIEhESSIpKSAgDQp9DQoNCg0Kc3VicGxvdChteV9wbG90WzE6NV0sIG5yb3dzID0gMiwgbWFyZ2luID0gMC4wNSkgJT4lIGxheW91dCh0aXRsZSA9ICdPREEgdnMgSERJJykNCg0KYGBgDQoNCmBgYHtyfQ0Kc3VicGxvdChteV9wbG90WzY6MTFdLCBucm93cyA9IDIsIG1hcmdpbiA9IDAuMDUpICU+JSBsYXlvdXQodGl0bGUgPSAnQ0MgdnMgSERJJykNCmBgYA0KDQpgYGB7cn0NCnN1YnBsb3QobXlfcGxvdFsxMjoxN10sIG5yb3dzID0gMiwgbWFyZ2luID0gMC4wNSkgJT4lIGxheW91dCh0aXRsZSA9ICdHRSB2cyBIREknKQ0KYGBgDQoNCg0KYGBge3J9DQpzdWJwbG90KG15X3Bsb3RbMTg6MjNdLCBucm93cyA9IDIsIG1hcmdpbiA9IDAuMDUpICU+JSBsYXlvdXQodGl0bGUgPSAnUFYgdnMgSERJJykNCmBgYA0KDQpgYGB7cn0NCnN1YnBsb3QobXlfcGxvdFsyNDoyOV0sIG5yb3dzID0gMiwgbWFyZ2luID0gMC4wNSkgJT4lIGxheW91dCh0aXRsZSA9ICdSUSB2cyBIREknKQ0KYGBgDQoNCmBgYHtyfQ0Kc3VicGxvdChteV9wbG90WzMwXSwgbnJvd3MgPSAxLCBtYXJnaW4gPSAwLjA1KSAlPiUgbGF5b3V0KHRpdGxlID0gJ1JMIHZzIEhESScpDQpgYGANCg0KTm8gc2UgdmUgdW5hIHJlbGFjaW9uIGNsYXJhLCBoYXkgdGFudG8gcGFpc2VzIGNvbiBwdW50ZW9zIGFsdG9zIHkgYmFqb3MgZGUgR09CIHF1ZSB0aWVuZW4gdGFudG8gSElEIGFsdG9zIG8gYmFqb3MNClF1aXphIHB1ZWRlIHZlcnNlIHVuYSBsZXZlIHJlbGFjaW9uIGRlIG1heW9yIHB1bnRlbyBlbiBHT0IgYWNvbXBhw7FhZG8gZGUgbWVqb3IgcHVudGVvIGRlbiBIREkNCg0KU2UgcmVhbGl6YXJhIGVsIG1pc21vIHByb2Nlc28gY29uIGVsIGNyZWNpbWllbnRvIG8gZGVjcmVjaW1pZW50byBkZSBIREkgYW51YWwgKG5vIHNlIHBlcmRlcmFuIGRhdG9zIGFsIGNhbGN1bGFyIGxhIGRpZmVyZW5jaWEgcG9ycXVlIHNlIGHDsWFkZSBlbCBhw7FvIDIwMDEgZW4gbGEgc2VsZWNjaW9uKQ0KDQojIE1hbmlwdWxhY2lvbiBkZSBkYXRvcyB1dGlsaXphbmRvIG9wZXJhZG9yIGRpZmVyZW5jaWENCg0KYGBge3J9DQpkYXRvc19tb2RlbF8yIDwtIGRhdG9zX3BhcGVyICU+JSANCiAgICAgICAgZmlsdGVyKCFpc28yYyAlaW4lIGMoJ1NTJywgJ1pXJywgJ0JUJywgJ0VSJywgJ0dXJywgJ0tQJywgJ0xCJywgJ05HJywgJ1BTJywgJ1NPJywgJ1ZVJywgJ0ZNJywgJ0tJJywgJ1RMJywgJ0NWJywgJ1NCJyksDQogICAgICAgICAgICAgICAheWVhciAlaW4lIGMoMTk5NSwgMTk5NiwgMTk5NywgMTk5OCwgMTk5OSwgMjAwMCkpICU+JQ0KICAgICAgICBzZWxlY3QoaXNvMmMsIHllYXIsIGhkaSwgRFQuT0RBLkFMTEQuQ0QsIERULk9EQS5BTExELktELCBEVC5PREEuT0RBVC5DRCwgRFQuT0RBLk9EQVQuS0QsIERULk9EQS5PREFULlBDLlpTLA0KICAgICAgICAgICAgICAgYWxsX29mKGdzdWIoIl8iLCAiLiIsIGdvYl9pbmRpY2F0b3JzKSkNCiAgICAgICAgICAgICAgICkNCg0KdmlzX2RhdChkYXRvc19tb2RlbF8yKQ0KYGBgDQoNCmBgYHtyfQ0KZGF0b3NfbW9kZWxfMyA8LSBkYXRvc19tb2RlbF8yICU+JQ0KICBhcnJhbmdlKGlzbzJjLCB5ZWFyKSAlPiUNCiAgbXV0YXRlKGhkaV9kaWZmID0gaGRpIC0gbGFnKGhkaSkpICU+JQ0KICBmaWx0ZXIoIXllYXIgJWluJSBjKDIwMDEpKQ0KDQpkYXRvc19tb2RlbF8zICU+JSBzZWxlY3QoaXNvMmMsIHllYXIsIGhkaSwgaGRpX2RpZmYpDQoNCnZpc19kYXQoZGF0b3NfbW9kZWxfMykNCmBgYA0KQ29uc3RydWNjaW9uIGRlIGdyYWZpY29zDQpgYGB7cn0NCm15X3Bsb3RfMyAgPC0gbGlzdCgpDQoNCmZvciAoY29sIGluIGNvbG5hbWVzKGRhdG9zX21vZGVsXzMpWzQ6MzNdKSB7DQogIG15X3Bsb3RfM1tbY29sXV0gPC0gcGxvdF9seSh4ID0gZGF0b3NfbW9kZWxfM1tbY29sXV0sIHkgPSBkYXRvc19tb2RlbF8zW1szNF1dLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbWFya2VycycsIG5hbWUgPSBwYXN0ZShjb2wsICJ2cyBIREkgZGlmZiIpKSAgDQp9DQoNCg0Kc3VicGxvdChteV9wbG90XzNbMTo1XSwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLjA1KSAlPiUgbGF5b3V0KHRpdGxlID0gJ09EQSB2cyBIREknKQ0KYGBgDQoNCmBgYHtyfQ0Kc3VicGxvdChteV9wbG90XzNbNjoxMV0sIG5yb3dzID0gMiwgbWFyZ2luID0gMC4wNSkgJT4lIGxheW91dCh0aXRsZSA9ICdDQyB2cyBIREkgZGlmZicpDQpgYGANCg0KYGBge3J9DQpzdWJwbG90KG15X3Bsb3RfM1sxMjoxN10sIG5yb3dzID0gMiwgbWFyZ2luID0gMC4wNSkgJT4lIGxheW91dCh0aXRsZSA9ICdHRSB2cyBIREkgZGlmZicpDQpgYGANCg0KYGBge3J9DQpzdWJwbG90KG15X3Bsb3RfM1sxODoyM10sIG5yb3dzID0gMiwgbWFyZ2luID0gMC4wNSkgJT4lIGxheW91dCh0aXRsZSA9ICdQViB2cyBIREkgZGlmZicpDQpgYGANCg0KYGBge3J9DQpzdWJwbG90KG15X3Bsb3RfM1syNDoyOV0sIG5yb3dzID0gMiwgbWFyZ2luID0gMC4wNSkgJT4lIGxheW91dCh0aXRsZSA9ICdSUSB2cyBIREkgZGlmZicpDQpgYGANCg0KYGBge3J9DQpzdWJwbG90KG15X3Bsb3RfM1szMF0sIG5yb3dzID0gMSwgbWFyZ2luID0gMC4wNSkgJT4lIGxheW91dCh0aXRsZSA9ICdSTCB2cyBIREkgZGlmZicpDQpgYGANCg0KUHJvYmFyIHVuIG51ZXZvIG1vZGVsbyB1c2Fkbm8gYWhvcmEgY29tbyB2YXJpYWJsZSBkZXBlbmRpZW50ZSBoZGlfZGlmZg0KYGBge3J9DQptb2RlbF8zIDwtIGxtKGhkaV9kaWZmIH4gRFQuT0RBLkFMTEQuQ0QgKyBDQy5FU1QgKyBHRS5FU1QgKyBQVi5FU1QgKyBSUS5FU1QgKyBSTC5FU1QsIGRhdGE9ZGF0b3NfbW9kZWxfMykNCnN1bW1hcnkobW9kZWxfMykNCmBgYA0KT3RybyBtb2RlbG8gYWhvcmEgdXNhbmRvIGxhcyB2YXJpYWJsZXMgUEVSLlJOSyBlbiB2ZXggZGUgRVNUDQpgYGB7cn0NCm1vZGVsXzQgPC0gbG0oaGRpX2RpZmYgfiBEVC5PREEuQUxMRC5DRCArIENDLlBFUi5STksgKyBHRS5QRVIuUk5LICsgUFYuUEVSLlJOSyArIFJRLlBFUi5STksgKyBSTC5FU1QsIGRhdGE9ZGF0b3NfbW9kZWxfMykNCnN1bW1hcnkobW9kZWxfNCkNCmBgYA0KVmllbmRvIGxhIGhpc3RvcmlhIGRlIGxhcyB2YXJpYWJsZXMgZW4gZWwgdGllbXBvIChwb3IgcGFpcykNCmBgYHtyfQ0KZGF0b3NfbW9kZWxfMyAlPiUgZmlsdGVyKGlzbzJjID09ICdBRicpICU+JSBwbG90X2x5KHggPSB+eWVhcikgJT4lIA0KICBhZGRfdHJhY2UoeSA9IH5oZGksIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbGluZXMrbWFya2VycycsIG5hbWUgPSAnaGRpJykgJT4lIA0KICBhZGRfdHJhY2UoeSA9IH5oZGlfZGlmZiwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcyttYXJrZXJzJywgbmFtZSA9ICdoZGkgZGlmZicpICU+JSANCiAgYWRkX3RyYWNlKHkgPSB+RFQuT0RBLkFMTEQuQ0QgLyAxMDAwMDAwMDAwMCwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcyttYXJrZXJzJywgbmFtZSA9ICdPREEnKSAgJT4lIA0KICBhZGRfdHJhY2UoeSA9IH5DQy5FU1QsIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbGluZXMrbWFya2VycycsIG5hbWUgPSAnQ0MnKSAlPiUgDQogIGFkZF90cmFjZSh5ID0gfkdFLkVTVCwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcyttYXJrZXJzJywgbmFtZSA9ICdHRScpICAlPiUgDQogIGFkZF90cmFjZSh5ID0gflBWLkVTVCwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcyttYXJrZXJzJywgbmFtZSA9ICdQVicpICAlPiUgDQogIGFkZF90cmFjZSh5ID0gflJRLkVTVCwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcyttYXJrZXJzJywgbmFtZSA9ICdSUScpICAlPiUgDQogIGFkZF90cmFjZSh5ID0gflJMLkVTVCwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcyttYXJrZXJzJywgbmFtZSA9ICdSTCcpIA0KYGBgDQoNCg0K